//********************************************************************************************************************//
//ORGANIZATION:
//AUTHOR: bpeng(bogers.peng@gmail.com)
//SUMMARY:
//********************************************************************************************************************//
#ifndef NATIVE_SYSTEM_BASE_BUFFER_H
#define NATIVE_SYSTEM_BASE_BUFFER_H

#ifndef NATIVE_SYSTEM_BASE_OBJECT_H
#include "System/Base/Object.h"
#endif
#ifndef NATIVE_SYSTEM_BASE_EQUALTO_H
#include "System/Base/EqualTo.h"
#endif

namespace Native { namespace System
{
    //****************************************************************************************************************//
    //EBufferImportRule
    //
    //****************************************************************************************************************//
    enum EBufferImportRule
    {
        BUFFER_IMPORT_RULE_THROW = 0,
        BUFFER_IMPORT_RULE_DISCARD,
        BUFFER_IMPORT_RULE_EXTEND
    };

    //****************************************************************************************************************//
    //CBuffer
    //
    //****************************************************************************************************************//
    NATIVE_DECLARE_CONST_OBJECT(CBuffer, C_BUFFER);
    //$ It warps a heap memory area what store binary data.
    class NATIVE_LIBRARY_EXPORT CBuffer :
        public CObject,
        public IEqualTo<CBuffer>
    {
        NATIVE_DECLARE_OBJECT;
        
        NATIVE_DECLARE_PROPERTY(public, public, size_t, UnitCapacity, _unit_capacity);
        NATIVE_DECLARE_PROPERTY(public, public, EBufferImportRule, ImportRule, _import_rule);

    public:
        static const size_t DEFAULT_UNIT_CAPACITY = 32;

        static size_t CalculateCapacity(size_t requestedSize, size_t unit_capacity);

    protected:
        //$
        size_t _capacity;
        size_t _cursor;
        pointer_t _data;
        
        size_t _Allocate(size_t request_capacity) throw();
        size_t _Reallocte(size_t request_capacity) throw();
        void _Deallocate();
        
    public:
        CBuffer();
        CBuffer(C_BUFFER& that) throw();
        CBuffer(CBuffer&& that);
        CBuffer(
            size_t initialCapacity,
            size_t unit_capacity = DEFAULT_UNIT_CAPACITY,
            EBufferImportRule import_rule = BUFFER_IMPORT_RULE_EXTEND) throw();
        virtual ~CBuffer();

    private:
        virtual void _Finalize();
    public:
        virtual bool operator==(C_BUFFER& rvalue) const;
        virtual bool operator!=(C_BUFFER& rvalue) const;

        size_t Usage() const;
        size_t Remain() const;
        size_t Capacity() const;
        void Clear();

        //$ Import source binary data into buffer.
        //# Source data pointer need to be imported.
        //# Imported size of source data
        //> Actual imported size
        size_t Import(pointer_t const source, size_t source_capacity) throw();

        //$ Import source buffer into buffer.
        //> Actual imported size.
        size_t Import(const CBuffer& source) throw();

        //$ Export binary data from @CBuffer to target.
        //> Actual imported size
        size_t Export(pointer_t const desination, size_t desination_capacity) const throw();

        //$ Append binary data to the end of orignal data in CBuffer.
        C_BUFFER& Append(pointer_t const source, size_t source_capacity) throw();
        C_BUFFER& Append(byte_t byte) throw();
        POINTER Pointer() const;

        C_BUFFER& operator=(C_BUFFER& rvalue) throw();
    };
}}

#endif
